package com.wh1200.mybatis.xmlless.model

import com.wh1200.mybatis.xmlless.model.base.BaseCriteria
import com.wh1200.mybatis.xmlless.model.criteria.CriteriaParameter
import com.wh1200.mybatis.xmlless.resolver.CriteriaResolver
import com.wh1200.mybatis.xmlless.util.indent

/**
 *
 * @author 吴昊
 * @date 2023/12/22 18:53
 * @since v0.0.0
 * @version 1.0
 */
class ChooseCriteria(
    private val property: String,
    parameters: List<CriteriaParameter>,
    methodInfo: MethodInfo,
    append: ConditionConnector = ConditionConnector.AND
) : BaseCriteria(
    parameters,
    methodInfo,
    append
) {

  private val testCriteria: List<WhenCriteria> = getCriteriaList()
  private val otherwiseCriteria: BaseCriteria? = getOtherwiseCriteria()

  override fun toSqlWithoutTest(): String {
    return toSql()
  }

  override fun getTableNames(): List<String> {
    val tables = testCriteria.map {
      it.getTableNames()
    }.flatten().toMutableList()
    if (otherwiseCriteria != null) {
      tables += otherwiseCriteria.getTableNames()
    }
    return tables.distinct()
  }

  override fun getColumns(extraJoins: List<JoinInfo>): List<SelectColumn> {
    return listOf()
  }

  override fun getProperty(): String {
    return property
  }

  override fun toSql(): String {
    val builder = StringBuilder()
    builder.appendLine("<choose>")
    builder.appendLine(testCriteria.joinToString("\n") {
      it.toSql()
    }.indent(1))
    if (otherwiseCriteria != null) {
      builder.appendLine("  <otherwise>")
      builder.appendLine(otherwiseCriteria.toSql().indent(2))
      builder.appendLine("  </otherwise>")
    }
    builder.append("</choose>")
    return builder.toString()
  }

  override fun toSql(parameterTest: TestInfo?, ifTag: String): String {
    return toSql()
  }

  override fun clone(parameters: List<CriteriaParameter>): BaseCriteria {
    return ChooseCriteria(property, parameters, methodInfo)
  }

  override fun clone(append: ConditionConnector): BaseCriteria {
    return ChooseCriteria(property, parameters, methodInfo, append)
  }

  private fun getOtherwiseCriteria(): BaseCriteria? {
    val parameter = getOnlyParameter()
    if (parameter != null) {
      return CriteriaResolver.getOtherWiseCriteria(parameter, methodInfo)
    }
    return null
  }

  private fun getCriteriaList(): List<WhenCriteria> {
    val parameter = getOnlyParameter()
    if (parameter != null) {
      return CriteriaResolver.getTestCriteriaInfo(parameter, methodInfo)
    }
    return listOf()
  }

}
